#include <allegro.h>
#include <iostream>
#include <string>
#include <cstdlib>
#include <fstream>
#include <cmath>
#include <vector>

void startAllegro();
void createMap(int w, int h);
void mapDraw();
bool isOnMap(int x, int y);
void save_map();
void loadbitmaps();
void reloadtxt(int x);
void addItem(int x, int y, int ID);


void createobject (std::string name, int warstwa, int szer, int wys,int tablica);
void readobjectfromfile(std::string filename);
void drawcurrentobject();
void systp();  ///system tworzenia tp


//END->OBIEKTY




char mapName[256];
std::string nazwaprzejscia = "";
int w, h;
bool fogOn;
int ** map;
int ** map_green;
int ** obiekttablica;
int ** tp_layer;
int klawisz = 0 ;
bool KEYs, KEYw, KEYe, KEYr;
bool isbck;


BITMAP * bufor;
BITMAP * tex;
BITMAP * tex_formap;
BITMAP * green_tex;
BITMAP * obj_tex;
BITMAP * menu;
BITMAP * icons_objects;//ikony dla obiektow
BITMAP * icons;//ikony dla innych plikow
BITMAP * choose;
BITMAP * tp;
BITMAP * menutp;
BITMAP * items;
BITMAP * submenu;



const int TILE_SIZE = 30;
int shiftX=100;
int shiftY=0;
int showX=0;
int showY=0;
int inputnazwa=0;

std::string a,tmp;
std::vector <std::string> przejcie;
std::vector <int> itemsground;
int iloscprzejsc=0;



int warstwa,szer,wys=-1;
int _menu=1;//aktywny wybor z menu
int _aktywny=0;//ID aktywne



int main()
{
    system("chcp 65001");
    std::cout << "EDYTOR MAP - TRYLOGIA\n";
    std::cout << "\nNazwa mapy (max 256 znakow): \n";
    std::cin.getline(mapName, 256);
    std::cout << "\nSzerokosc (max: ";
    std::cin >> w;
    std::cout << "\nWysokosc: ";
    std::cin >> h;
    std::cout << "\nFogOfWar: ";
    std::cin >> fogOn;
    std::cout << "\n";

    startAllegro();
    createMap(w, h);
    bufor = create_bitmap(900, 640);
    loadbitmaps();


    while (!key[KEY_ESC])
    {
                mapDraw();

      masked_blit(menu,bufor,0,0,0,200,menu->w,menu->h);//MENU
      masked_blit(choose,bufor,0,0,0,(_menu *30 +170) ,choose->w,choose->h);
      masked_blit(submenu,bufor,0,0,0,170 ,submenu->w,submenu->h);


      if (mouse_x < 100) {if (showX > 0) {showX--;}}
      if (mouse_y < 30) {if (showY > 0) {showY--;}}
      if (mouse_x > 770) {if (showX < w * 30 - 900) {showX++;}}
      if (mouse_y > 610) {if (showY < h * 30 - 640) {showY++;}}



            if (mouse_b==1 )
            {
                if (mouse_x<100 && mouse_y>200 &&mouse_y < 200+menu->h ) // _menu
                    {
                    _menu=(mouse_y-200)/30 +1 ;
                    reloadtxt(_menu);
                    _aktywny=0;
                    }

                if (_menu == 1 && mouse_x >100)
                    map[int((mouse_x+showX - shiftX)/TILE_SIZE)][int((mouse_y+showY - shiftY)/TILE_SIZE)] = _aktywny;

                if (_menu == 2 && !(mouse_x<100 && mouse_y>200 &&mouse_y < 200+menu->h )&& mouse_x >100)
                    map_green[int((mouse_x+showX - shiftX)/TILE_SIZE)][int((mouse_y+showY - shiftY)/TILE_SIZE)] = _aktywny;

                    if (_menu == 3 && !(mouse_x<100 && mouse_y>200 &&mouse_y < 200+menu->h )&& mouse_x >100)//OBIEKTY
                    {
                        icons = load_bmp("icons.bmp",default_palette);

                        switch (_aktywny)
                        {
                            case 0:
                               readobjectfromfile("drzewo.obj");
                                break;
                            case 1:
                               readobjectfromfile("krzak.obj");
                                break;
                        }
                        drawcurrentobject();
                    }

                if (_menu==5 && mouse_x >100)
                    { ///przejscia na inne mapy
                    tp_layer[int((mouse_x+showX - shiftX)/TILE_SIZE)][int((mouse_y+showY - shiftY)/TILE_SIZE)] = 1;
                    systp();
                    }



                if (_menu==6 && mouse_x>100)
                {
                    addItem(int(mouse_x+showX - shiftX),int(mouse_y+showY - shiftY),_aktywny);
                }

            }




                if (_menu == 1 && mouse_b==2 && mouse_x>100)
                    map[int((mouse_x+showX - shiftX)/TILE_SIZE)][int((mouse_y+showY - shiftY)/TILE_SIZE)] = 0;

                if (_menu == 2 && mouse_b==2 && mouse_x>100)
                    map_green[int((mouse_x+showX - shiftX)/TILE_SIZE)][int((mouse_y+showY - shiftY)/TILE_SIZE)] = -1;

                if (key[KEY_LSHIFT] && mouse_b==2)
                    {
                         map_green[int((mouse_x+showX - shiftX)/TILE_SIZE)][int((mouse_y+showY - shiftY)/TILE_SIZE)] = -1;
                         map[int((mouse_x+showX - shiftX)/TILE_SIZE)][int((mouse_y+showY - shiftY)/TILE_SIZE)] = 0;
                    }


            if (!(mouse_x<100 && mouse_y>200 &&mouse_y < 200+menu->h ))
                masked_blit(icons,bufor,_aktywny*30,0,mouse_x,mouse_y,30,30);

            if (key[KEY_W] && !KEYw)
            {
                 KEYw=true;
                _aktywny++;
                if (_aktywny>tex->w/30 ) _aktywny=0;

            } else if (!key[KEY_W]) KEYw = false;


            if (key[KEY_S] && !KEYs)
            {
                KEYs=true;
                _aktywny--;
                if (_aktywny<0) _aktywny=0 ;

            } else if (!key[KEY_S]) KEYs = false;


       blit( bufor, screen, 0, 0, 0, 0,900,640);

    }



    save_map();
    allegro_exit();
    return 0;
}
END_OF_MAIN();


void startAllegro()
{
    allegro_init();
    install_keyboard();
    install_timer();
    set_color_depth(32);
    set_gfx_mode(GFX_AUTODETECT_WINDOWED, 900, 640, 0, 0);
    install_mouse();
    show_mouse(screen);
    scare_mouse();
}

void createMap(int w, int h)
{
    map = new int*[w];
    map_green = new int*[w];
    tp_layer = new int *[w];

    for (int i = 0; i < w; i++)
    {
        map[i] = new int[h];
        map_green[i] = new int[h];
        tp_layer[i] = new int[h];
        for (int j = 0; j < h; j++)
        {
            map[i][j] = 0;
            map_green[i][j] = -1;
            tp_layer[i][j] = -1;
        }
    }
}

void mapDraw()
{
    clear_to_color(bufor, 0x000000);

    if (w * TILE_SIZE < bufor->w) shiftX = (bufor->w - w * TILE_SIZE)/2;
    if (h * TILE_SIZE < bufor->h) shiftY = (bufor->h - h * TILE_SIZE)/2;

    //rysowanie mapy
    for (int j = 0; j < bufor->h / TILE_SIZE + 2; j++)
    {
        for (int i = 0; i < bufor->w / TILE_SIZE + 2; i++)
        {
            int x = i+showX/TILE_SIZE;
            int y = j+showY/TILE_SIZE;
            if (!isOnMap(x * TILE_SIZE, y * TILE_SIZE)) continue;
            masked_blit(tex_formap, bufor, map[x][y] * TILE_SIZE, 0, i * TILE_SIZE - ((int)showX % TILE_SIZE) + shiftX, j * TILE_SIZE - ((int)showY % TILE_SIZE) + shiftY, TILE_SIZE, TILE_SIZE);
        }
    }
    //zielen i woda
    for (int j = 0; j < bufor->h / TILE_SIZE + 2; j++)
    {
        for (int i = 0; i < bufor->w / TILE_SIZE + 2; i++)
        {
            int x = i+showX/TILE_SIZE;
            int y = j+showY/TILE_SIZE;
            if (!isOnMap(x * TILE_SIZE, y * TILE_SIZE)) continue;
            masked_blit(green_tex, bufor, map_green[x][y] * TILE_SIZE, 0, i * TILE_SIZE - ((int)showX % TILE_SIZE) + shiftX, j * TILE_SIZE - ((int)showY % TILE_SIZE) + shiftY, TILE_SIZE, TILE_SIZE);
        }
    }

    ///TELEPORTS:
    for (int j = 0; j < bufor->h / TILE_SIZE + 2; j++)
    {
        for (int i = 0; i < bufor->w / TILE_SIZE + 2; i++)
        {
            int x = i+showX/TILE_SIZE;
            int y = j+showY/TILE_SIZE;
            if (!isOnMap(x * TILE_SIZE, y * TILE_SIZE)) continue;
            if (tp_layer[x][y]==1)
            masked_blit(tp, bufor, 0, 0, i * TILE_SIZE - ((int)showX % TILE_SIZE) + shiftX, j * TILE_SIZE - ((int)showY % TILE_SIZE) + shiftY, TILE_SIZE, TILE_SIZE);
        }
    }

    ///ITEMS GROUND:

    for (int i=0; i < itemsground.size(); i+=3)
    {
        masked_blit(items,bufor, i+2 * TILE_SIZE,0,i,i+1,TILE_SIZE,TILE_SIZE);
    }

}

void fixwater()
{
    for (int j = 0; j < bufor->h / TILE_SIZE + 2; j++)
    {
        for (int i = 0; i < bufor->w / TILE_SIZE + 2; i++)
        {
            int x = i+showX/TILE_SIZE;
            int y = j+showY/TILE_SIZE;

            if (map_green[x][y]==18)
            {
                map_green[x-1][y]=17;
                map_green[x+1][y]=19;
                //2:
                map_green[x-1][y-1]=14;
                map_green[x][y-1]=15;
                map_green[x+1][y-1]=16;
                //3:
                map_green[x-1][y-2]=11;
                map_green[x][y-2]=12;
                map_green[x+1][y-2]=13;

            }

             }
    }


}



bool isOnMap(int x, int y)
{
    return x >= 0 && y >= 0 && x < w * TILE_SIZE && y < h * TILE_SIZE;
}


void save_map()
{
    std::fstream file;
    std::string name = "..\\..\\Data\\Maps\\";
    name += mapName;
    name += ".map";
    file.open(name.c_str(), std::ios::out);
    if (!file) return;

    file << w << " " << h << "\n";

    for (int i = 0; i < h; i++)
    {
        for (int j = 0; j < w; j++)
            file << map[j][i] << " ";
        file << "\n";
    }
    file << "\n";
    for (int i = 0; i < h; i++)
    {
        for (int j = 0; j < w; j++)
            file << map_green[j][i] << " ";
        file << "\n";
    }
    file << "\n";
    file << fogOn;
    file << "\n";
    ///TP:
    file << iloscprzejsc << "\n";

    for (int i=0; i < (iloscprzejsc*iloscprzejsc) -1; i++)
    {
         file << przejcie[i] << " ";
         std::cout<<przejcie[i]<<"\n";
    }
     file.close();

    std::cout << "Mapa zapisana pomyslnie!";
}


void loadbitmaps()
{

    tex =tex_formap= load_bmp("..\\..\\GFX\\texturpack.bmp", default_palette);
    choose=load_bmp("choose.bmp",default_palette);
    green_tex = load_bmp("..\\..\\GFX\\texturepack_green.bmp", default_palette);
    icons =load_bmp("..\\..\\GFX\\texturpack.bmp", default_palette);
    tp = load_bmp("tp.bmp",default_palette);
    menutp = load_bmp("menutp.bmp", default_palette);
    submenu = load_bmp ("submenu.bmp", default_palette);

    menu = load_bmp("buttons.bmp",default_palette);
    icons_objects=load_bmp("icons.bmp",default_palette);
    items=load_bmp("..\\..\\GFX\\items.bmp",default_palette);

}


void reloadtxt(int x)
{
    switch (x)
    {
        case 1:
            tex = icons =load_bmp("..\\..\\GFX\\texturpack.bmp", default_palette);

            break;
        case 2:
            tex = icons =load_bmp("..\\..\\GFX\\texturepack_green.bmp", default_palette);

            break;
        case 3:
            icons = load_bmp("icons.bmp",default_palette);
            tex  = load_bmp("..\\..\\GFX\\texturpack.bmp", default_palette);
            break;
        case 5:
            tex = load_bmp("..\\..\\GFX\\texturpack.bmp", default_palette);
            break;
        case 6:
            tex = items;
            break;

    }
}

void createobject(std::string name, int warstwa, int szer, int wys,int tablica[])
{
    //nie skonczone
    std::fstream plik;
    name += ".obj";
    plik.open(name.c_str(), std::ios::out);
    plik<<warstwa<<"\n"<<szer<<" "<<wys<<"\n";

    plik.close();

}


void readobjectfromfile(std::string filename)
{

    std::fstream plikobiektu;

    plikobiektu.open(filename.c_str(),std::ios::in);
    plikobiektu>>warstwa;
    plikobiektu>>szer;
    plikobiektu>>wys;

    obiekttablica = new int *[szer];
     for (int c=0 ; c<wys;c++)
        obiekttablica[c] = new int [wys];



    for (int o=0 ; o<szer;o++)
    {
        for (int b = 0; b<wys ; b++)
            plikobiektu>>obiekttablica[o][b];
    }

}


void drawcurrentobject()
{
    int X=mouse_x;
    int Y=mouse_y;

      for (int t=0;t<szer;t++)
        for (int z=0;z<wys;z++)
            if (map_green[int((mouse_x+showX - shiftX)/TILE_SIZE)+t][int((mouse_y+showY - shiftY)/TILE_SIZE)+z]!=-1) return;


    for (int i=0 ; i<szer ;i++)
        for (int j=0 ;j<wys;j++)
        {
            if (warstwa==0)
                map[int((mouse_x+showX - shiftX)/TILE_SIZE)+i][int((mouse_y+showY - shiftY)/TILE_SIZE)+j]=obiekttablica[j][i];
            if (warstwa==1)
            {
                map_green[int((mouse_x+showX - shiftX)/TILE_SIZE)+i][int((mouse_y+showY - shiftY)/TILE_SIZE)+j]=obiekttablica[j][i];
            }
        }




}


void systp()
{
    int klawisz=0;

    clear_to_color( menutp, makecol( 206, 159, 0 ) );

    while (!key[KEY_ENTER])
    {

        textout_ex(menutp,font,"Wpisz nazwe mapy do ktorej tworzysz przejscie: ",3,5,makecol(0,0,0),-1);
        masked_blit(menutp,screen,0,0,230,280,menutp->w, menutp->h);

        for (int i=0; i<37; i++)
        {
            if (key[i])
            {
            nazwaprzejscia += char(i+96);
            key[i]=false;
            }
        }

        if (key[KEY_BACKSPACE] && nazwaprzejscia.size() > 1 && !isbck )
        {
            isbck=true;
            tmp="";

            for (int i =0 ; i< nazwaprzejscia.size()-1; i++)
                tmp += char(nazwaprzejscia[i]);


            nazwaprzejscia.clear();
            nazwaprzejscia=tmp;
            clear_to_color( menutp, makecol( 206, 159, 0 ) );
            textout_ex(menutp,font,"Wpisz nazwe mapy do ktorej tworzysz przejscie: ",3,5,makecol(0,0,0),-1);
            textout_ex(menutp,font,nazwaprzejscia.c_str(),3,20,makecol(0,0,0),-1);

        }else if (!key[KEY_BACKSPACE]) isbck=false;



        textout_ex(menutp,font,nazwaprzejscia.c_str(),3,20,makecol(0,0,0),-1);

    }

    iloscprzejsc++;
    przejcie.push_back(itoa(int((mouse_x+showX - shiftX)/TILE_SIZE),(char*)a.c_str(),10));
    przejcie.push_back(itoa(int((mouse_y+showY - shiftY)/TILE_SIZE),(char*)a.c_str(),10));
    przejcie.push_back(nazwaprzejscia);
    przejcie.push_back("\n");

    nazwaprzejscia.clear();



}


void addItem(int x, int y, int ID)
{

    itemsground.push_back(x+int(showY - shiftY));
    itemsground.push_back(y+int(showY - shiftY));
    itemsground.push_back(ID);

}








